﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using LiteTools.constants.dicts;
using LiteTools.constants.exceptions;
using LiteTools.domains;
using LiteTools.domains.db;
using LiteTools.service.converters.data_parser;
using LiteTools.tools;
using Sunny.UI;

namespace LiteTools.forms
{
    public partial class ToolMainForm : UIForm
    {
        private FormatData _currentData;
        private bool showTlvDesc = false;

        public ToolMainForm()
        {
            InitializeComponent();
            SetAllLabelBlack();
            SetComboxesSelections();
            SetButtonsDefaultEnables();
            SetDefaultText();
            ResetBuilder();
        }

        private void SetDefaultText()
        {
            symbol.Text = @",";
            times.Text = @"8";
        }

        /// <summary>
        /// 设置所有的按钮为默认策略的可用性
        /// </summary>
        private void SetButtonsDefaultEnables()
        {
            result.ReadOnly = true;
            num_result.ReadOnly = true;
            formated_text.ReadOnly = true;
        }

        /// <summary>
        /// 设置所有的Combox组件选择默认的选项
        /// </summary>
        private void SetComboxesSelections()
        {
            tool_type.SelectedIndex = 0;
            split_symbol.SelectedIndex = 4;
            types.SelectedIndex = 0;
            format_type.SelectedIndex = 0;
            build_type.SelectedIndex = 0;
            GetSpecificTypes();
        }

        private void GetSpecificTypes()
        {
            var tlvTagFamilies = TlvTagFamilyHelper.GetTlvTagFamily();
            specific_type.Clear();
            foreach (var tlvTagFamily in tlvTagFamilies)
            {
                specific_type.Items.Add(tlvTagFamily);
            }

            specific_type.DisplayMember = "ttf_name";
            specific_type.SelectedIndex = 0;
        }

        /// <summary>
        /// 手动设置Lable的颜色，不然跟主题色不匹配，将会使用白色显示，导致无法看见内容
        /// </summary>
        private void SetAllLabelBlack()
        {
            // uiLabel1.ForeColor = Color.Black;
            // uiLabel2.ForeColor = Color.Black;
            // uiLabel3.ForeColor = Color.Black;
            // uiLabel4.ForeColor = Color.Black;
            // uiLabel5.ForeColor = Color.Black;
            // uiLabel6.ForeColor = Color.Black;
            // uiLabel7.ForeColor = Color.Black;
            // uiLabel8.ForeColor = Color.Black;
            // uiLabel9.ForeColor = Color.Black;
            // uiLabel10.ForeColor = Color.Black;
            // uiLabel15.ForeColor = Color.Black;
            // uiLabel11.ForeColor = Color.Black;
            // uiLabel12.ForeColor = Color.Black;
            // uiLabel16.ForeColor = Color.Black;
            // uiLabel17.ForeColor = Color.Black;
            // uiLabel18.ForeColor = Color.Black;
        }

        /// <summary>
        /// 当选择的字符串工具改变时，更新一些按钮的显示状态，刷新功能
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void SelectedTypeChanged(object sender, EventArgs e)
        {
            // 每次切换先清理一下内容
            str_todo.Text = string.Empty;
            result.Text = string.Empty;
            // 只有是分割的时候才显示分割的策略
            uiLabel4.Visible = tool_type.SelectedIndex == 1;
            uiLabel5.Visible = tool_type.SelectedIndex == 1;
            uiLabel6.Visible = tool_type.SelectedIndex == 1;
            uiLabel7.Visible = tool_type.SelectedIndex == 1;
            symbol.Visible = tool_type.SelectedIndex == 1;
            times.Visible = tool_type.SelectedIndex == 1;
            split_symbol.Visible = tool_type.SelectedIndex == 1;
            str_todo.Height = tool_type.SelectedIndex == 1 ? 132 : 206;
        }

        private void symbol_Leave(object sender, EventArgs e)
        {
            if (symbol.Text.Length != 1)
            {
                UIMessageTip.Show(symbol, "分隔符只能填写长度为1的简单字符！", TipStyle.Red, 500, true);
            }
        }

        private void times_Leave(object sender, EventArgs e)
        {
            var isValid = int.TryParse(times.Text, out var number) && number > 0;
            if (!isValid)
            {
                UIMessageTip.Show(times, "次数必须是正整数！", TipStyle.Red, 500, true);
            }
        }

        private string ToAscii(string handleText)
        {
            var input = handleText;
            if (Regex.IsMatch(input, "^[0-9]*$"))
            {
                var asciiBytes = new byte[input.Length / 3];
                try
                {
                    for (var i = 0; i < asciiBytes.Length; i++)
                    {
                        var byteString = input.Substring(i * 3, 3);
                        var asciiByte = byte.Parse(byteString);
                        asciiBytes[i] = asciiByte;
                    }
                }
                catch (Exception)
                {
                    UIMessageTip.Show(str_todo, "暂不支持ASCII码转中文！", TipStyle.Orange, 500, true);
                    return "暂不支持ASCII码转中文！";
                }

                return Encoding.UTF8.GetString(asciiBytes);
            }
            else
            {
                var asciiBytes = Encoding.UTF8.GetBytes(input);
                var stringBuilder = new StringBuilder();
                foreach (var b in asciiBytes)
                {
                    stringBuilder.Append(b);
                }

                return stringBuilder.ToString();
            }
        }

        private string TrimSpaces(string context)
        {
            var builder = context.Replace("\n", "");
            builder = builder.Replace("\t", "");
            builder = builder.Replace(" ", "");
            return builder;
        }

        private string StrSplit(string handleText)
        {
            // 再检查一次分隔符是不是长度为1
            if (symbol.Text.Length != 1)
            {
                UIMessageTip.Show(str_todo, "分隔符只能填写长度为1的简单字符！", TipStyle.Red, 500, true);
            }

            // 再检查一次次数是不是数字，必须是正整数
            var isValid = int.TryParse(times.Text, out var number) && number > 0;
            if (!isValid)
            {
                UIMessageTip.Show(str_todo, "次数必须是正整数！", TipStyle.Red, 500, true);
            }

            if (split_symbol.SelectedIndex < 0)
            {
                UIMessageTip.Show(str_todo, "分隔符类型必须选择有效值！", TipStyle.Red, 500, true);
            }

            var builder = new StringBuilder();
            var count = 0;
            foreach (var t in handleText)
            {
                if (t == symbol.Text.ToCharArray()[0])
                {
                    builder.Append(symbol.Text);
                    count++;
                    if (count != number) continue;
                    string appendStr;
                    switch (split_symbol.SelectedIndex)
                    {
                        case 0:
                            appendStr = " | ";
                            break;
                        case 1:
                            appendStr = " ==> ";
                            break;
                        case 2:
                            appendStr = " ";
                            break;
                        case 3:
                            appendStr = "\t";
                            break;
                        case 4:
                            appendStr = "\n";
                            break;
                        default:
                            appendStr = split_symbol.SelectedItem.ToString();
                            break;
                    }

                    builder.Append(appendStr);
                    count = 0;
                }
                else
                {
                    builder.Append(t);
                }
            }

            return builder.ToString();
        }

        private void str_todo_Click(object sender, EventArgs e)
        {
        }

        private void str_todo_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != (char)Keys.F1)
            {
                return;
            }

            DoAnalyze();
        }

        private void DoAnalyze()
        {
            var handleText = str_todo.Text;
            if (!string.IsNullOrEmpty(cut_head.Text))
            {
                handleText = handleText.Substring(handleText.IndexOf(cut_head.Text, StringComparison.Ordinal) +
                                                  cut_head.Text.Length);
            }

            if (!string.IsNullOrEmpty(cut_tail.Text))
            {
                handleText = handleText.Substring(0, handleText.Length - cut_tail.Text.Length);
            }

            string builder;
            switch (tool_type.SelectedIndex)
            {
                case 0:
                    builder = TrimSpaces(handleText);
                    break;
                case 1:
                    builder = StrSplit(handleText);
                    break;
                case 2:
                    builder = ToAscii(handleText);
                    break;
                default:
                    builder = string.Empty;
                    break;
            }

            result.Text = builder;
        }

        private void analyze_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(str_todo.Text))
            {
                UIMessageTip.ShowError(str_todo, "没有内容，无需转换！", 1500, true);
                return;
            }

            DoAnalyze();
        }

        private void charge_Click(object sender, EventArgs e)
        {
            var text = plain_text.Text;
            switch (types.SelectedIndex)
            {
                case 0:
                    // 123, 21, 123, 43 ==> 0x7B, 0x15, 0x7B, 0x2B
                    var strings = text.Split(",");
                    var value1 = GetValue(strings);

                    if (value1 == null)
                    {
                        return;
                    }

                    num_result.Text = value1;
                    return;
                case 1:
                    // 123021123043 ==> 0x7B, 0x15, 0x7B, 0x2B，要求必须每三位是一个十进制数，不足3为的补0
                    if (text.Length % 3 != 0)
                    {
                        UIMessageTip.ShowError(plain_text, "内容长度必须是3的倍数，请核实！", 1500, true);
                        return;
                    }

                    var chunks = new List<string>();
                    for (var i = 0; i < text.Length; i += 3)
                    {
                        var length = Math.Min(3, text.Length - i);
                        var chunk = text.Substring(i, length);
                        chunks.Add(chunk);
                    }

                    var value = GetValue(chunks);

                    if (value == null)
                    {
                        return;
                    }

                    num_result.Text = value;
                    return;
                case 2:
                    // 0x7B, 0x15, 0x7B, 0x2B ==> 7B157B2B
                    var hexString = GetHexString(text);

                    if (hexString == null)
                    {
                        return;
                    }

                    num_result.Text = hexString;
                    return;
                case 3:
                    // 7B157B2B ==> 0x7B, 0x15, 0x7B, 0x2B，每两位为一个十六进制数

                    if (text.Length % 2 != 0)
                    {
                        UIMessageTip.ShowError(plain_text, "内容长度必须是2的倍数，请核实！", 1000, true);
                        return;
                    }

                    var hexes = new List<string>();
                    for (var i = 0; i < text.Length; i += 2)
                    {
                        var length = Math.Min(2, text.Length - i);
                        var chunk = text.Substring(i, length);
                        hexes.Add(chunk);
                    }

                    var hexValue = GetHexValue(hexes);
                    if (hexValue == null)
                    {
                        return;
                    }

                    num_result.Text = hexValue;
                    return;
            }
        }

        private string GetHexValue(List<string> hexs)
        {
            var list = new List<string>();
            foreach (var num in hexs)
            {
                if (!Regex.IsMatch(num, "^[0-9A-Fa-f]{2}$"))
                {
                    UIMessageTip.ShowError(plain_text, "内容必须全部是使用英文逗号【,】分隔的十进制数。错误的值：【" + num + "】！", 1000, true);
                    return null;
                }

                list.Add("0x" + num.ToUpper());
            }

            return string.Join(", ", list);
        }

        private string GetHexString(string text)
        {
            var strings = text.Split(",");
            // 去除十六进制前缀 "0x"
            for (var i = 0; i < strings.Length; i++)
            {
                strings[i] = strings[i].Replace("0x", "").ToUpper().Trim();
                if (!(Convert.ToInt32(strings[i], 16) > 255)) continue;
                UIMessageTip.ShowError(plain_text, "所有的值不能超过一个byte的最大范围【0x00~0xFF】。错误的值：【" + strings[i] + "】！", 1000,
                    true);
                return null;
            }

            // 连接字符串
            return string.Join("", strings);
        }

        private string GetValue(IEnumerable<string> strings)
        {
            var list = new List<string>();
            foreach (var num in strings)
            {
                var tryParse = int.TryParse(num, out var realNum);
                if (!tryParse)
                {
                    UIMessageTip.ShowError(plain_text, "内容必须全部是使用英文逗号【,】分隔的十进制数。错误的值：【" + num + "】！", 1000,
                        true);
                    return null;
                }

                if (realNum > 255)
                {
                    UIMessageTip.ShowError(plain_text, "每个十进制数都不能超过一个字节表示【小于256】。错误的数字：【" + num + "】！", 1000, true);
                    return null;
                }

                list.Add("0x" + realNum.ToString("X2"));
            }

            return string.Join(", ", list);
        }

        private void plain_text_KeyPress(object sender, KeyPressEventArgs e)
        {
        }

        private void result_DoubleClick(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(result.Text))
            {
                UIMessageTip.ShowError(result, "没有内容无法完成复制操作！", 1500, true);
                return;
            }

            Clipboard.SetText(result.Text);
            UIMessageTip.ShowOk(result, "转换结果已经复制到剪切板！", 1500, true);
        }

        private void num_result_DoubleClick(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(num_result.Text))
            {
                UIMessageTip.ShowError(num_result, "没有内容无法完成复制操作！", 1500, true);
                return;
            }

            Clipboard.SetText(num_result.Text);
            UIMessageTip.ShowOk(num_result, "转换结果已经复制到剪切板！", 1500, true);
        }

        private void types_SelectedIndexChanged(object sender, EventArgs e)
        {
            num_result.Text = string.Empty;
            plain_text.Text = string.Empty;
        }

        private void format_type_SelectedIndexChanged(object sender, EventArgs e)
        {
            category.Items.Clear();
            var value = ComboxDicts.FORMAT_COMBOX[format_type.SelectedItem.ToString()];
            foreach (var formatType in value)
            {
                category.Items.Add(formatType);
            }

            category.SelectedIndex = 0;
        }

        private void uiButton1_Click(object sender, EventArgs e)
        {
            RefreshTlvResult();
            showTlvDesc = !showTlvDesc;
        }

        private void RefreshTlvResult()
        {
            if (string.IsNullOrEmpty(format_plain_text.Text))
            {
                UIMessageTip.ShowError(format_plain_text, "没有内容无法进行转换操作！", 1500, true);
                return;
            }

            SpecificParser specificParser;
            try
            {
                specificParser =
                    ParserContainer.GetParser(format_type.SelectedItem.ToString(), category.SelectedItem.ToString());
            }
            catch (Exception)
            {
                UIMessageTip.ShowError(format_plain_text, "没有找到合适的解析器，请联系作者添加解析方法！", 1500, true);
                return;
            }

            var tagWhiteList = GetTagWhiteList();
            try
            {
                _currentData = specificParser.Handle(format_plain_text.Text.Replace(" ", "").Trim(), tagWhiteList);
            }
            catch (Exception)
            {
                UIMessageTip.ShowError(format_plain_text, "解析源数据错误，请确认是一个合法争取的TLV数据再执行解析！", 1500, true);
                return;
            }

            if (_currentData == null)
            {
                UIMessageTip.ShowError(format_plain_text, "没有得到解析结果，请确认输入信息后重试！", 1500, true);
                return;
            }

            string convert2Str;
            try
            {
                var tlvTagFamily = (TlvTagFamilyHelper.TlvTagFamily)specific_type.SelectedItem;
                convert2Str = _currentData.Convert2Str(showTlvDesc, int.Parse(tlvTagFamily.ttf_id));
            }
            catch (Exception)
            {
                UIMessageTip.ShowError(format_plain_text, "得到解析结果，但解析的结果打印逻辑有误，请联系作者定位", 1500, true);
                return;
            }

            formated_text.Text = convert2Str;
        }

        private List<TagInfoHelper.TagInfo> GetTagWhiteList()
        {
            var tlvTagFamilies = TlvTagFamilyHelper.GetTlvTagFamily();
            var selectedItem = (TlvTagFamilyHelper.TlvTagFamily)specific_type.SelectedItem;
            return (from tlvTagFamily in tlvTagFamilies
                where tlvTagFamily.ttf_name == selectedItem.ttf_name
                select TagInfoHelper.GetTagInfoByFamily(tlvTagFamily.ttf_id)).FirstOrDefault();
        }

        private void formated_text_KeyDown(object sender, KeyEventArgs e)
        {
            if (_currentData == null)
            {
                return;
            }

            if (e.KeyCode != Keys.F11) return;

            if (string.IsNullOrEmpty(formated_text.Text))
            {
                UIMessageTip.ShowError(formated_text, "没有数据需要预览！", 1500, true);
                return;
            }

            var contentMaxLength = StringUtils.GetSizeFromGivenStr(formated_text.Text);
            var tlvViewer = new TlvViewer(contentMaxLength["w"], contentMaxLength["h"], formated_text.Text);
            tlvViewer.ShowDialog();
        }

        private void formated_text_DoubleClick(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(formated_text.Text))
            {
                UIMessageTip.ShowError(formated_text, "没有内容无法完成复制操作！", 1500, true);
                return;
            }

            Clipboard.SetText(formated_text.Text);
            UIMessageTip.ShowOk("内容复制成功！");
        }

        private void specific_config_Click(object sender, EventArgs e)
        {
            var specificConfigForm = new SpecificConfigForm();
            specificConfigForm.ShowDialog();
        }

        private void add_node_Click(object sender, EventArgs e)
        {
            var selectedNode = data_tree.SelectedNode;
            if (selectedNode == null)
            {
                return;
            }

            var tlvNodeEditor = new TlvNodeEditor();
            var dialogResult = tlvNodeEditor.ShowDialog();
            if (dialogResult == DialogResult.OK)
            {
                var resultTlvNode = tlvNodeEditor.GetResultTlvNode();
                data_tree.SelectedNode.Nodes.Add(resultTlvNode);
            }

            RefreshTreeView();
            CheckEnableAdd();
            // 显示TreeView
            data_tree.ExpandAll();
        }

        private static void SetNodeText(TreeNode node)
        {
            node.Text = $"【tag - {node.Name}】\t 【value - {node.Tag}】";

            foreach (TreeNode childNode in node.Nodes)
            {
                SetNodeText(childNode);
            }
        }

        private void RefreshTreeView()
        {
            foreach (TreeNode node in data_tree.Nodes)
            {
                SetNodeText(node);
            }
        }

        private void remove_node_Click(object sender, EventArgs e)
        {
            data_tree.SelectedNode.Remove();
        }

        private void edit_node_Click(object sender, EventArgs e)
        {
            var selectedNode = data_tree.SelectedNode;
            if (selectedNode.Name == "root")
            {
                UIMessageTip.ShowError(data_tree, "不允许修改根节点信息！", 1500, true);
                return;
            }

            var tlvNodeEditor = new TlvNodeEditor(selectedNode);
            var dialogResult = tlvNodeEditor.ShowDialog();
            var resultTlvNode = tlvNodeEditor.GetResultTlvNode();
            if (dialogResult != DialogResult.OK) return;
            data_tree.SelectedNode.Name = resultTlvNode.Name;
            data_tree.SelectedNode.Tag = resultTlvNode.Tag;
            RefreshTreeView();
        }

        private void do_build_Click(object sender, EventArgs e)
        {
            var treeNode = data_tree.Nodes[0];
            var formatData = DataUtil.GenTlvDataFromTreeView(treeNode);
            try
            {
                var tlvTagFamily = (TlvTagFamilyHelper.TlvTagFamily)specific_type.SelectedItem;
                var formated = formatData.Convert2Str(false, int.Parse(tlvTagFamily.ttf_id));
                var ok = UIMessageBox.ShowAsk(formated);
                if (ok)
                {
                    var replace = formated.Replace("\n", "").Replace("\t", "").Replace(" ", "");
                    Clipboard.SetText(replace);
                }
            }
            catch (Exception exception)
            {
                if (exception is LiteToolsException)
                {
                    UIMessageTip.ShowError(data_tree, "数据可能不全，无法生成TLV！请核实后重试！", 1500, true);
                    return;
                }

                UIMessageTip.ShowError(data_tree, "未知的错误！", 1500, true);
            }
        }

        private void build_type_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!ComboxDicts.BUILD_COMBOX.ContainsKey(build_type.SelectedItem.ToString())) return;
            var list = ComboxDicts.BUILD_COMBOX[build_type.SelectedItem.ToString()];
            if (list == null || list.Count == 0)
            {
                TurnMoreOff();
                return;
            }

            TurnMoreOn();
            uiComboBox1.Items.Clear();
            foreach (var conf in list)
            {
                uiComboBox1.Items.Add(conf);
            }

            uiComboBox1.SelectedIndex = 0;
        }

        private void TurnMoreOff()
        {
            uiLabel14.Visible = false;
            uiComboBox1.Enabled = false;
            uiComboBox1.Visible = false;
        }

        private void TurnMoreOn()
        {
            uiLabel14.Visible = true;
            uiComboBox1.Enabled = true;
            uiComboBox1.Visible = true;
        }

        private void re_build_Click(object sender, EventArgs e)
        {
            ResetBuilder();
        }

        private void ResetBuilder()
        {
            data_tree.Nodes.Clear();
            var treeNode = new TreeNode
            {
                Name = "root",
                Tag = "根节点"
            };
            data_tree.Nodes.Add(treeNode);
            RefreshTreeView();
            data_tree.SelectedNode = data_tree.Nodes[0];
        }

        private void data_tree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            CheckEnableAdd();
        }

        private void CheckEnableAdd()
        {
            var selectedNode = data_tree.SelectedNode;
            if (selectedNode.Name == "root")
            {
                add_node.Enabled = selectedNode.Nodes.Count == 0;
            }
            else
            {
                // 结构化的TLV节点才允许添加子节点
                if (selectedNode.Tag == null || selectedNode.Tag.ToString() == string.Empty)
                {
                    add_node.Enabled = true;
                }
                else
                {
                    add_node.Enabled = false;
                }
            }
        }

        private void data_tree_ItemDrag(object sender, ItemDragEventArgs e)
        {
            // 开始拖动节点
            DoDragDrop(e.Item, DragDropEffects.Move);
        }

        private void data_tree_DragEnter(object sender, DragEventArgs e)
        {
            // 确保拖动的是节点
            e.Effect = e.Data.GetDataPresent(typeof(TreeNode)) ? DragDropEffects.Move : DragDropEffects.None;
        }

        private void data_tree_DragDrop(object sender, DragEventArgs e)
        {
            // 获取拖动的节点
            var draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

            // 获取鼠标下方的节点
            var targetNode = data_tree.GetNodeAt(data_tree.PointToClient(new System.Drawing.Point(e.X, e.Y)));

            if (draggedNode == null || targetNode == null) return;
            // 检查被替换位置的节点的Name属性是否为"root"
            if (targetNode.Name == "root")
            {
                MessageBox.Show("不能替换为根节点！");
                return;
            }

            // 检查替换只能是同级节点的位置替换
            if (draggedNode.Parent != targetNode.Parent)
            {
                MessageBox.Show("只能在同级节点之间替换位置！");
                return;
            }

            // 移除拖动的节点
            draggedNode.Remove();

            // 根据鼠标位置插入节点
            if (targetNode.Parent != null)
            {
                targetNode.Parent.Nodes.Insert(targetNode.Index, draggedNode);
            }
            else
            {
                data_tree.Nodes.Insert(targetNode.Index, draggedNode);
            }
        }

        private void format_plain_text_TextChanged(object sender, EventArgs e)
        {
            showTlvDesc = false;
        }

        private void data_bind_config_Click(object sender, EventArgs e)
        {
            new ConfigDataServiceForm().ShowDialog();
        }
    }
}